import { Router } from 'express'
import { body, validationResult } from 'express-validator'
import { supabase } from '../server'
import { logger } from '../utils/logger'
import { asyncHandler, createError } from '../middleware/errorHandler'
import { AuthenticatedRequest, requireSubscription, logUserActivity } from '../middleware/auth'

const router = Router()

// Subscription plan configurations
const SUBSCRIPTION_PLANS = {
  free: {
    name: 'Free',
    price: 0,
    billing_cycle: null,
    features: {
      max_saved_papers: 10,
      max_alerts: 3,
      max_search_queries: 50,
      advanced_search: false,
      api_access: false,
      priority_support: false,
      analytics: false,
      export_capabilities: false,
      bulk_download: false,
      collaboration_features: false,
      custom_categories: false
    }
  },
  premium: {
    name: 'Premium',
    price: 9.99,
    billing_cycle: 'monthly',
    features: {
      max_saved_papers: 1000,
      max_alerts: 50,
      max_search_queries: 1000,
      advanced_search: true,
      api_access: true,
      priority_support: true,
      analytics: true,
      export_capabilities: true,
      bulk_download: true,
      collaboration_features: true,
      custom_categories: true
    }
  },
  academic: {
    name: 'Academic',
    price: 4.99,
    billing_cycle: 'monthly',
    features: {
      max_saved_papers: 500,
      max_alerts: 25,
      max_search_queries: 500,
      advanced_search: true,
      api_access: true,
      priority_support: true,
      analytics: false,
      export_capabilities: true,
      bulk_download: true,
      collaboration_features: false,
      custom_categories: true
    }
  },
  institutional: {
    name: 'Institutional',
    price: 99.99,
    billing_cycle: 'monthly',
    features: {
      max_saved_papers: -1, // unlimited
      max_alerts: -1, // unlimited
      max_search_queries: -1, // unlimited
      advanced_search: true,
      api_access: true,
      priority_support: true,
      analytics: true,
      export_capabilities: true,
      bulk_download: true,
      collaboration_features: true,
      custom_categories: true
    }
  }
}

// Helper function to check validation results
const checkValidation = (req: any, res: any) => {
  const errors = validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(400).json({
      success: false,
      message: 'Validation failed',
      errors: errors.array()
    })
  }
  return null
}

// Get available subscription plans
router.get('/plans', asyncHandler(async (req, res) => {
  res.json({
    success: true,
    plans: SUBSCRIPTION_PLANS
  })
}))

// Get current user subscription
router.get('/current',
  logUserActivity('view_subscription'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: subscription, error } = await supabase
        .from('subscriptions')
        .select('*')
        .eq('user_id', userId)
        .eq('status', 'active')
        .order('created_at', { ascending: false })
        .limit(1)
        .single()

      if (error && error.code !== 'PGRST116') { // PGRST116 = no rows returned
        throw createError('Failed to fetch subscription: ' + error.message, 500)
      }

      // If no active subscription found, return free plan info
      if (!subscription) {
        return res.json({
          success: true,
          subscription: {
            plan_type: 'free',
            status: 'active',
            features: SUBSCRIPTION_PLANS.free.features,
            usage_metrics: {
              saved_papers_count: 0,
              active_alerts_count: 0,
              monthly_searches: 0,
              api_requests_count: 0,
              storage_used_mb: 0,
              last_updated: new Date().toISOString()
            }
          }
        })
      }

      res.json({
        success: true,
        subscription
      })

    } catch (error) {
      logger.error('Get subscription error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Create or upgrade subscription
router.post('/subscribe',
  [
    body('plan_type').isIn(['premium', 'academic', 'institutional']),
    body('billing_cycle').optional().isIn(['monthly', 'yearly']),
    body('payment_method').optional().isIn(['stripe', 'paypal']),
    body('payment_token').optional().isString()
  ],
  logUserActivity('subscribe'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const { plan_type, billing_cycle = 'monthly', payment_method, payment_token } = req.body

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const planConfig = SUBSCRIPTION_PLANS[plan_type as keyof typeof SUBSCRIPTION_PLANS]
      if (!planConfig) {
        return res.status(400).json({
          success: false,
          message: 'Invalid subscription plan'
        })
      }

      // Cancel any existing active subscription
      await supabase
        .from('subscriptions')
        .update({
          status: 'cancelled',
          end_date: new Date().toISOString(),
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .eq('status', 'active')

      // Create new subscription
      const subscriptionData = {
        user_id: userId,
        plan_type,
        status: 'active',
        start_date: new Date().toISOString(),
        billing_cycle,
        payment_method,
        payment_id: payment_token, // In real implementation, this would be from payment processor
        features: planConfig.features,
        usage_metrics: {
          saved_papers_count: 0,
          active_alerts_count: 0,
          monthly_searches: 0,
          api_requests_count: 0,
          storage_used_mb: 0,
          last_updated: new Date().toISOString()
        },
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString()
      }

      const { data: subscription, error } = await supabase
        .from('subscriptions')
        .insert(subscriptionData)
        .select()
        .single()

      if (error) {
        logger.error('Subscription creation failed', { error: error.message, userId })
        throw createError('Subscription creation failed: ' + error.message, 400)
      }

      // Update user profile subscription status
      await supabase
        .from('user_profiles')
        .update({
          subscription_status: plan_type,
          subscription_start_date: subscriptionData.start_date,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)

      logger.info('Subscription created successfully', { 
        userId, 
        planType: plan_type, 
        billingCycle: billing_cycle 
      })

      res.json({
        success: true,
        message: `Successfully subscribed to ${planConfig.name} plan`,
        subscription
      })

    } catch (error) {
      logger.error('Subscription error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId,
        planType: plan_type
      })
      throw error
    }
  })
)

// Cancel subscription
router.post('/cancel',
  logUserActivity('cancel_subscription'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      // Get current active subscription
      const { data: currentSub, error: fetchError } = await supabase
        .from('subscriptions')
        .select('*')
        .eq('user_id', userId)
        .eq('status', 'active')
        .single()

      if (fetchError || !currentSub) {
        return res.status(404).json({
          success: false,
          message: 'No active subscription found'
        })
      }

      if (currentSub.plan_type === 'free') {
        return res.status(400).json({
          success: false,
          message: 'Cannot cancel free plan'
        })
      }

      // Cancel the subscription
      const { error } = await supabase
        .from('subscriptions')
        .update({
          status: 'cancelled',
          end_date: new Date().toISOString(),
          updated_at: new Date().toISOString()
        })
        .eq('id', currentSub.id)

      if (error) {
        logger.error('Subscription cancellation failed', { error: error.message, userId })
        throw createError('Subscription cancellation failed: ' + error.message, 400)
      }

      // Create new free subscription
      const freeSubData = {
        user_id: userId,
        plan_type: 'free' as const,
        status: 'active' as const,
        start_date: new Date().toISOString(),
        features: SUBSCRIPTION_PLANS.free.features,
        usage_metrics: {
          saved_papers_count: 0,
          active_alerts_count: 0,
          monthly_searches: 0,
          api_requests_count: 0,
          storage_used_mb: 0,
          last_updated: new Date().toISOString()
        },
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString()
      }

      await supabase.from('subscriptions').insert(freeSubData)

      // Update user profile
      await supabase
        .from('user_profiles')
        .update({
          subscription_status: 'free',
          subscription_end_date: new Date().toISOString(),
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)

      logger.info('Subscription cancelled successfully', { userId, previousPlan: currentSub.plan_type })

      res.json({
        success: true,
        message: 'Subscription cancelled successfully. You have been moved to the free plan.'
      })

    } catch (error) {
      logger.error('Cancel subscription error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Get subscription usage statistics
router.get('/usage',
  logUserActivity('view_usage'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: subscription, error } = await supabase
        .from('subscriptions')
        .select('usage_metrics, features, plan_type')
        .eq('user_id', userId)
        .eq('status', 'active')
        .single()

      if (error) {
        return res.status(404).json({
          success: false,
          message: 'No active subscription found'
        })
      }

      // Calculate usage percentages
      const usage = subscription.usage_metrics
      const features = subscription.features
      
      const usageStats = {
        saved_papers: {
          used: usage.saved_papers_count || 0,
          limit: features.max_saved_papers,
          percentage: features.max_saved_papers === -1 
            ? 0 
            : Math.round(((usage.saved_papers_count || 0) / features.max_saved_papers) * 100)
        },
        alerts: {
          used: usage.active_alerts_count || 0,
          limit: features.max_alerts,
          percentage: features.max_alerts === -1 
            ? 0 
            : Math.round(((usage.active_alerts_count || 0) / features.max_alerts) * 100)
        },
        monthly_searches: {
          used: usage.monthly_searches || 0,
          limit: features.max_search_queries,
          percentage: features.max_search_queries === -1 
            ? 0 
            : Math.round(((usage.monthly_searches || 0) / features.max_search_queries) * 100)
        },
        api_requests: {
          used: usage.api_requests_count || 0,
          limit: features.api_access ? (features.max_search_queries * 10) : 0
        },
        storage: {
          used_mb: usage.storage_used_mb || 0,
          limit_mb: subscription.plan_type === 'institutional' ? -1 : 100
        }
      }

      res.json({
        success: true,
        plan_type: subscription.plan_type,
        usage_stats: usageStats,
        last_updated: usage.last_updated
      })

    } catch (error) {
      logger.error('Get usage error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update usage metrics (internal API)
router.put('/usage',
  [
    body('saved_papers_count').optional().isInt({ min: 0 }),
    body('active_alerts_count').optional().isInt({ min: 0 }),
    body('monthly_searches').optional().isInt({ min: 0 }),
    body('api_requests_count').optional().isInt({ min: 0 }),
    body('storage_used_mb').optional().isNumeric({ no_symbols: false })
  ],
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const updates = req.body

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      // Get current subscription
      const { data: subscription, error: fetchError } = await supabase
        .from('subscriptions')
        .select('usage_metrics')
        .eq('user_id', userId)
        .eq('status', 'active')
        .single()

      if (fetchError || !subscription) {
        return res.status(404).json({
          success: false,
          message: 'No active subscription found'
        })
      }

      // Update usage metrics
      const updatedMetrics = {
        ...subscription.usage_metrics,
        ...updates,
        last_updated: new Date().toISOString()
      }

      const { error } = await supabase
        .from('subscriptions')
        .update({
          usage_metrics: updatedMetrics,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .eq('status', 'active')

      if (error) {
        logger.error('Usage update failed', { error: error.message, userId })
        throw createError('Usage update failed: ' + error.message, 400)
      }

      res.json({
        success: true,
        message: 'Usage metrics updated successfully',
        usage_metrics: updatedMetrics
      })

    } catch (error) {
      logger.error('Update usage error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Get subscription history
router.get('/history',
  logUserActivity('view_subscription_history'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: subscriptions, error } = await supabase
        .from('subscriptions')
        .select('id, plan_type, status, start_date, end_date, billing_cycle, payment_method, created_at')
        .eq('user_id', userId)
        .order('created_at', { ascending: false })

      if (error) {
        logger.error('Get subscription history failed', { error: error.message, userId })
        throw createError('Failed to fetch subscription history: ' + error.message, 500)
      }

      res.json({
        success: true,
        subscriptions: subscriptions || []
      })

    } catch (error) {
      logger.error('Get subscription history error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Check subscription feature access
router.get('/features/:feature',
  requireSubscription(['premium', 'academic', 'institutional']),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id
    const featureName = req.params.feature

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: subscription, error } = await supabase
        .from('subscriptions')
        .select('features, plan_type')
        .eq('user_id', userId)
        .eq('status', 'active')
        .single()

      if (error || !subscription) {
        return res.status(403).json({
          success: false,
          message: 'No active subscription found'
        })
      }

      const hasFeature = subscription.features[featureName as keyof typeof subscription.features]

      res.json({
        success: true,
        has_feature: Boolean(hasFeature),
        plan_type: subscription.plan_type,
        feature_value: hasFeature
      })

    } catch (error) {
      logger.error('Check feature access error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId,
        feature: featureName
      })
      throw error
    }
  })
)

export default router